/**
 * Copyright (c) 2010
 * Bert Young. UESTC. 
 */

#ifndef BERT_ALLOCATOR_H
#define BERT_ALLOCATOR_H

#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
#include "MemoryPool.h"

namespace Bert
{

/**
 * Allocator for STL
 */

template <typename T>
class Allocator
{
public:
	typedef size_t size_type;
	typedef ptrdiff_t difference_type;
	typedef T * pointer;
	typedef const T * const_pointer;
	typedef T& reference;
	typedef const T& const_reference;
	typedef T value_type;

#if 0
	Allocator()
	{
	}
	Allocator(const Allocator<T> &)
	{
	}
	template <typename U>
	Allocator(const Allocator<U> &)
	{
		// this will hide the default construtor and copy constructor
	}
#endif

	template < typename U>
	struct rebind
	{
		typedef Allocator<U> other;
	};

	pointer address( reference value ) const
	{
		return &value;
	}

 	const_pointer address( const_reference value ) const
	{
		return &value;
	}

 	size_type max_size() const throw()
	{
		return size_t(-1) / sizeof(T);
	}

 	pointer allocate(size_type num, const_pointer hint = NULL )
	{
		return (pointer)MemoryPool::allocate(num * sizeof(T));
	}

	void deallocate(pointer p, size_type num)
	{
		MemoryPool::deallocate(p, num * sizeof(T) );
	}

 	void construct(pointer p, const_reference value=T())
	{
		new (p)T(value);
	}

	void destroy(pointer p)
	{
		p->~T();
	}
};

template<typename T1, typename T2>
inline bool operator==(const Allocator<T1>&, const Allocator<T2>&)
{
	return true;
}

template<typename T1, typename T2>
inline bool operator!=(const Allocator<T1>&, const Allocator<T2>&)
{
	return false;
}

template <typename T>
class vector : public ::std::vector<T, Allocator<T> >
{
public:
	typedef ::std::vector<T, Allocator<T> > Base;
	typedef typename Base::size_type size_type;
	typedef typename Base::value_type value_type;
	typedef typename Base::allocator_type allocator_type;

	vector()
	{
	}

	explicit vector(size_type n, const value_type& value = value_type(), const allocator_type& a = allocator_type()) : Base(n,value, a)
	{
	}
	
	vector( const vector & x ) : Base(x)
	{
	}

	template<typename _InputIterator>
        vector(_InputIterator first, _InputIterator last, const allocator_type& a = allocator_type())
	: Base(first, last, a)
	{
	}
};

template <typename T>
class list : public ::std::list<T, Allocator<T> >
{
public:
	typedef ::std::list<T, Allocator<T> > Base; 
	typedef typename Base::size_type size_type;
	typedef typename Base::value_type value_type;
	typedef typename Base::allocator_type allocator_type;

	list()
	{
	}

	explicit list(size_type n, const value_type& value = value_type(), const allocator_type& a = allocator_type()) : Base(n,value, a)
	{
	}
	
	list( const list& x ) : Base(x)
	{
	}

	template<typename _InputIterator>
        list(_InputIterator first, _InputIterator last, const allocator_type& a = allocator_type())
	: Base(first, last, a)
	{
	}
};

} // namespace Bert

#endif

